package img

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/gif"
	"image/jpeg"
	"image/png"
	"imagehandle/internal/types"
	"io/ioutil"
	"math"
	"net/http"
	"path/filepath"
	"runtime"

	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"golang.org/x/image/font"
)

// TextBrush 字体相关
type TextBrush struct {
	FontType  *truetype.Font
	FontSize  float64
	FontColor *image.Uniform
	TextWidth int
}

// NewTextBrush 新生成笔刷
func NewTextBrush(FontFilePath string, FontSize float64, FontColor *image.Uniform, textWidth int) (*TextBrush, error) {
	fontFile, err := ioutil.ReadFile(FontFilePath)
	if err != nil {
		return nil, err
	}
	fontType, err := truetype.Parse(fontFile)
	if err != nil {
		return nil, err
	}
	if textWidth <= 0 {
		textWidth = 20
	}
	return &TextBrush{FontType: fontType, FontSize: FontSize, FontColor: FontColor, TextWidth: textWidth}, nil
}

// DrawRectOnImageAndSave 图片上画多个框
func DrawRectOnImage(imageData []byte, scopes [][]*types.Axis) (*image.RGBA, error) {
	//判断图片类型
	var backgroud image.Image
	var err error
	filetype := http.DetectContentType(imageData)
	switch filetype {
	case "image/jpeg", "image/jpg":
		backgroud, err = jpeg.Decode(bytes.NewReader(imageData))
		if err != nil {
			fmt.Println("jpeg error")
			return nil, err
		}

	case "image/gif":
		backgroud, err = gif.Decode(bytes.NewReader(imageData))
		if err != nil {
			return nil, err
		}

	case "image/png":
		backgroud, err = png.Decode(bytes.NewReader(imageData))
		if err != nil {
			return nil, err
		}
	default:
		return nil, err
	}
	des := Image2RGBA(backgroud)
	// 获取到ttf文件目录
	// 获取当前文件的绝对路径  
    _, filename, _, ok := runtime.Caller(0)  
    if !ok {  
        return nil, errors.New("failed to get current file path")  
    }  
  
    // 向上回溯到项目根目录（这里假设internal/pkg/img相对于根目录是固定的）  
    rootDir := filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(filename))))
  
    // 拼接字体文件的完整路径  
    fontFilePath := filepath.Join(rootDir, "arial.ttf")
	fmt.Println(fontFilePath)
	//新建笔刷
	textBrush, _ := NewTextBrush(fontFilePath, 15, image.Black, 15)
	var c *freetype.Context
	c = freetype.NewContext()
	c.SetDPI(72)
	c.SetFont(textBrush.FontType)
	c.SetHinting(font.HintingFull)
	c.SetFontSize(textBrush.FontSize)
	c.SetClip(des.Bounds())
	c.SetDst(des)
	cGreen := image.NewUniform(color.RGBA{
		R: 255,
		G: 0,
		B: 0,
		A: 255,
	})

	c.SetSrc(cGreen)
	for _, scope := range scopes {
		//知道两点坐标求出对应的斜率方程
		// 其中对应点有(x0,y0)&(x1,y1) (x0,y0)&(x2,y2) (x3,y3)&(x2,y2) (x3,y3)&(x1,y1)
		if len(scope) != 4 {
			return nil, errors.New("绘制位置信息错误")
		}
		for i := 1; i < len(scope); i++ {
			ppre := *scope[i-1]
			pnow := *scope[i]
			err = DrawLine(&ppre, &pnow, c)
			if err != nil {
				return nil, err
			}
		}
		ppre := *scope[len(scope) - 1]
		pnow := *scope[0]
		err = DrawLine(&ppre, &pnow, c)
		if err != nil {
			return nil, err
		}
	}
	return des, nil
}

// 画 y = kx + b 的线
func DrawLine(start, end *types.Axis, ctx *freetype.Context) error {
	// y = kx + b
	if math.Abs(end.X-start.X) > math.Abs(end.Y-start.Y) {
		var max, min int
		var k float64
		if int(math.Abs(end.X-start.X)) == 0 {
			return errors.New("除0异常")
		}
		if end.X > start.X {
			max = int(end.X)
			min = int(start.X)
			k = (end.Y - start.Y) / (end.X - start.X)
		} else {
			min = int(end.X)
			max = int(start.X)
			k = (start.Y - end.Y) / (start.X - end.X)
		}
		var b float64 = start.Y - k*start.X
		for i := min; i <= max; i++ {
			ctx.DrawString(".", freetype.Pt(int(i), int(k*float64(i)+b)))
		}
	} else {
		var max, min int
		var k float64
		if int(math.Abs(end.Y-start.Y)) == 0 {
			return errors.New("除0异常")
		}
		if end.Y > start.Y {
			max = int(end.Y)
			min = int(start.Y)
			k = (end.X - start.X) / (end.Y - start.Y)
		} else {
			min = int(end.Y)
			max = int(start.Y)
			k = (start.X - end.X) / (start.Y - end.Y)
		}
		var b float64 = start.X - k*start.Y
		for i := min; i <= max; i++ {
			ctx.DrawString(".", freetype.Pt(int(k*float64(i)+b), int(i)))
		}
	}
	return nil
}

// Image2RGBA Image2RGBA
func Image2RGBA(img image.Image) *image.RGBA {

	baseSrcBounds := img.Bounds().Max

	newWidth := baseSrcBounds.X
	newHeight := baseSrcBounds.Y

	des := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight)) // 底板
	//首先将一个图片信息存入jpg
	draw.Draw(des, des.Bounds(), img, img.Bounds().Min, draw.Over)

	return des
}
